package com.wz.controller;

import com.wz.config.Normal;
import com.wz.pojo.Block;
import com.wz.service.BlockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.web3j.abi.EventEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Event;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.methods.request.EthFilter;
import org.web3j.protocol.http.HttpService;
import rx.Subscription;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import static org.web3j.protocol.core.DefaultBlockParameterName.EARLIEST;
import static org.web3j.protocol.core.DefaultBlockParameterName.LATEST;

/**
 * @program: demo
 * @description:
 * @author: Wangzheng
 * @create: 2020-12-21 14:13
 **/
@RestController
@RequestMapping("/BlockDemo")
public class BlockDemo {

	@Autowired
	private static Web3j web3j;

	@Autowired
	private static Subscription subscription;

	@Autowired
	private BlockService blockService;

	//查询快的信息
	@RequestMapping("/getBlock")
	public HashMap<String, Object> getBlock(){
		try {
			return blockService.getBlockResult();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	//拿数据
	@RequestMapping("/getBlockData")
	public HashMap<Integer, Block> getBlockData(){
		try {
			return blockService.getBlockDataToMap();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	//插数据库
	@RequestMapping("/insertBlockData")
	public String insertBlockData(){
		try {
			return blockService.insertBlockData();
		} catch (Exception e) {
			e.printStackTrace();
			return "失败";
		}
	}
	
	
	
	         //插数据库//
	@RequestMapping("/insertDB")
	public void insertDB(){
		try {
			blockService.insertDbData();
		} catch (Exception e) {
			e.printStackTrace();
			
		}
	}



	
	
	
	
	
	
	
	
	
	
	/**
	 * 遍历旧区块、交易
	 * http://localhost:8080/Filter/replayFilter
	 */
	@RequestMapping("/replayFilter")
	public HashMap<String, Object> replayFilter() {
		HashMap<String, Object> map = new HashMap<>();
		BigInteger bigBlockNum = blockService.findBigBlockNum();
		//遍历旧区块
		for (int i = 0; i < bigBlockNum.intValue(); i++) {
			subscription = Web3j.build(new HttpService(Normal.SERVER)).replayBlocksObservable(
					DefaultBlockParameter.valueOf(String.valueOf(EARLIEST)),
					DefaultBlockParameter.valueOf(String.valueOf(LATEST)),
					false).subscribe(ethBlock -> {
				BigInteger number = ethBlock.getBlock().getNumber();
				map.put("hash" + String.valueOf(number), ethBlock.getBlock().getHash());
				map.put("blockNumber" + String.valueOf(number), ethBlock.getBlock().getNumber());
				map.put("parentHash" + String.valueOf(number), ethBlock.getBlock().getParentHash());
				map.put("miner" + String.valueOf(number), ethBlock.getBlock().getMiner());
				map.put("difficulty" + String.valueOf(number), ethBlock.getBlock().getDifficulty());
				map.put("gasLimit" + String.valueOf(number), ethBlock.getBlock().getGasLimit());
				map.put("gasUsed" + String.valueOf(number), ethBlock.getBlock().getGasUsed());
				map.put("timestamp" + String.valueOf(number), ethBlock.getBlock().getTimestamp());
				map.put("number" + String.valueOf(number), ethBlock.getBlock().getNumber());
				map.put("size" + String.valueOf(number), ethBlock.getBlock().getSize());
			});
		}
		subscription = Web3j.build(new HttpService(Normal.SERVER)).replayBlocksObservable(
				DefaultBlockParameter.valueOf(String.valueOf(EARLIEST)),
				DefaultBlockParameter.valueOf(String.valueOf(LATEST)),
				false).subscribe(ethBlock -> {

			//System.out.println("=================区块信息 start =====================");
			//System.out.println("Number" + " : " + ethBlock.getBlock().getNumber());
//					System.out.println("Timestamp" + " : " + ethBlock.getBlock().getTimestamp());
//					System.out.println("Hash" + " : " + ethBlock.getBlock().getHash());
//					System.out.println("parentHash" + " : " + ethBlock.getBlock().getParentHash());
//					System.out.println("Miner" + " : " + ethBlock.getBlock().getMiner());
//					System.out.println("GasLimit" + " : " + ethBlock.getBlock().getGasLimit());
//					System.out.println("GasUsed" + " : " + ethBlock.getBlock().getGasUsed());
//					System.out.println("ParentHash" + " : " + ethBlock.getBlock().getParentHash());
//					System.out.println("Size" + " : " + ethBlock.getBlock().getSize());
//					System.out.println("Difficulty" + " : " + ethBlock.getBlock().getDifficulty());
			//System.out.println("Transactions" + " : " + ethBlock.getBlock().getTransactions());
			//System.out.println("Author" + " : " + ethBlock.getBlock().getAuthor());
			//System.out.println("ExtraData" + " : " + ethBlock.getBlock().getExtraData());
			//System.out.println("GasUsedRaw" + " : " + ethBlock.getBlock().getGasUsedRaw());
			//System.out.println("Nonce" + " : " + ethBlock.getBlock().getNonce());
			//System.out.println("TransactionsRoot" + " : " + ethBlock.getBlock().getTransactionsRoot());
			//System.out.println("DifficultyRaw" + " : " + ethBlock.getBlock().getDifficultyRaw());
			//System.out.println("GasLimitRaw" + " : " + ethBlock.getBlock().getGasLimitRaw());
			//System.out.println("LogsBloom" + " : " + ethBlock.getBlock().getLogsBloom());
			//System.out.println("TimestampRaw" + " : " + ethBlock.getBlock().getTimestampRaw());
			//System.out.println("=================区块信息 over =====================");
		});
		//遍历旧交易
		subscription = Web3j.build(new HttpService(Normal.SERVER)).replayTransactionsObservable(
				DefaultBlockParameter.valueOf(String.valueOf(EARLIEST)),
				DefaultBlockParameter.valueOf(String.valueOf(LATEST))).subscribe(transaction -> {

//					System.out.println("=========遍历旧交易 star ===========");
//					System.out.println("transaction Hash " + " : " + transaction.getHash());
//					System.out.println("transaction BlockHash " + " : " + transaction.getBlockHash());
//					System.out.println("transaction To " + " : " + transaction.getTo());
//					System.out.println("transaction From " + " : " + transaction.getFrom());
//					System.out.println("transaction Input " + " : " + transaction.getInput());
//					System.out.println("transaction PublicKey " + " : " + transaction.getPublicKey());
//					System.out.println("transaction BlockNumberRaw " + " : " + transaction.getBlockNumberRaw());
//					System.out.println("transaction BlockNumber " + " : " + transaction.getBlockNumber());
//					System.out.println("transaction Creates " + " : " + transaction.getCreates());
//					System.out.println("transaction GasPriceRaw " + " : " + transaction.getGasPriceRaw());
//					System.out.println("transaction GasPrice " + " : " + transaction.getGasPrice());
//					System.out.println("transaction Gas " + " : " + transaction.getGas());
//					System.out.println("transaction Nonce " + " : " + transaction.getNonce());
//					System.out.println("transaction Value " + " : " + transaction.getValue());
//					System.out.println("transaction ValueRaw " + " : " + transaction.getValueRaw());
//					System.out.println("=========遍历旧交易 over ===========");
		});
		return map;
	}


	/**
	 * Event log相关
	 * 监听合约event
	 */
	@RequestMapping("/ContractEvent/{contractAddress}")
	public void ContractEvent(@PathVariable("contractAddress") String contractAddress) {
		Web3j web3j = Web3j.build(new HttpService(Normal.SERVER));
		EthFilter filter = new EthFilter(
				EARLIEST,
				LATEST,
				contractAddress);
		Event event = new Event("Transfer",
				Arrays.<TypeReference<?>>asList(
						new TypeReference<Address>() {
						},
						new TypeReference<Address>() {
						}
				),
				Arrays.<TypeReference<?>>asList(
						new TypeReference<Uint256>() {
						}
				)
		);

		String topicData = EventEncoder.encode(event);
		filter.addSingleTopic(topicData);
		System.out.println("topicData" + " : " + topicData);

		web3j.ethLogObservable(filter).subscribe(log -> {
			System.out.println("BlockNumber" + " : " + log.getBlockNumber());
			System.out.println("getTransactionHash" + " : " + log.getTransactionHash());
			System.out.println("getAddress" + " : " + log.getAddress());
			System.out.println("getData" + " : " + log.getData());
			System.out.println("getType" + " : " + log.getType());
			List<String> topics = log.getTopics();
			for (String topic : topics) {
				System.out.println("topic" + " : " + topic);
			}
		});


	}


	/**
	 * 新区块监听
	 * http://localhost:8080/Filter/newBlockFilter
	 */
	@RequestMapping("/newBlockFilter")
	public void newBlockFilter() {
		subscription = Web3j.build(new HttpService(Normal.SERVER)).
				blockObservable(false).
				subscribe(block -> {

					System.out.println("=========new block come in===========");
					System.out.println("block number" + block.getBlock().getNumber());
					System.out.println("block hash" + block.getBlock().getHash());
					System.out.println("block Transactions" + block.getBlock().getTransactions());
					System.out.println("block ExtraData" + block.getBlock().getExtraData());
					System.out.println("block Timestamp" + block.getBlock().getTimestamp());
					System.out.println("block Miner" + block.getBlock().getMiner());
					System.out.println("block Author" + block.getBlock().getAuthor());
					System.out.println("block GasLimit" + block.getBlock().getGasLimit());
					System.out.println("block GasUsed" + block.getBlock().getGasUsed());
					System.out.println("block TransactionsRoot" + block.getBlock().getTransactionsRoot().toString());
					System.out.println("block ParentHash" + block.getBlock().getParentHash());
					System.out.println("block Size" + block.getBlock().getSize());
					System.out.println("block Nonce" + block.getBlock().getNonce());
					System.out.println("block GasUsedRaw" + block.getBlock().getGasUsedRaw());
					System.out.println("=========over===========");
				});
	}

	/**
	 * 新交易监听 拿到交易的 transactionHash
	 * http://localhost:8080/Filter/newTransactionFilter
	 */
	@RequestMapping("newTransactionFilter")
	public void newTransactionFilter() {
		subscription = Web3j.build(new HttpService(Normal.SERVER)).
				transactionObservable().
				subscribe(transaction -> {

					System.out.println("=========transaction come in===========");
					System.out.println("transaction Hash " + " : " + transaction.getHash());
					System.out.println("transaction BlockHash " + " : " + transaction.getBlockHash());
					System.out.println("transaction To " + " : " + transaction.getTo());
					System.out.println("transaction From " + " : " + transaction.getFrom());
					System.out.println("transaction Input " + " : " + transaction.getInput());
					System.out.println("transaction PublicKey " + " : " + transaction.getPublicKey());
					System.out.println("transaction BlockNumberRaw " + " : " + transaction.getBlockNumberRaw());
					System.out.println("transaction BlockNumber " + " : " + transaction.getBlockNumber());
					System.out.println("transaction Creates " + " : " + transaction.getCreates());
					System.out.println("transaction GasPriceRaw " + " : " + transaction.getGasPriceRaw());
					System.out.println("transaction GasPrice " + " : " + transaction.getGasPrice());
					System.out.println("transaction Nonce " + " : " + transaction.getNonce());
					System.out.println("transaction Value " + " : " + transaction.getValue());
					System.out.println("transaction ValueRaw " + " : " + transaction.getValueRaw());
					System.out.println("=========over===========");
				});

	}


}
